package com.earnings.okhttputils.utils.OkHttp;


import android.content.Context;
import android.content.SharedPreferences;
import android.net.ConnectivityManager;

import com.earnings.okhttputils.utils.OkHttp.builder.GetBuilder;
import com.earnings.okhttputils.utils.OkHttp.builder.HeadBuilder;
import com.earnings.okhttputils.utils.OkHttp.builder.OtherRequestBuilder;
import com.earnings.okhttputils.utils.OkHttp.builder.PostFileBuilder;
import com.earnings.okhttputils.utils.OkHttp.builder.PostFormBuilder;
import com.earnings.okhttputils.utils.OkHttp.builder.PostStringBuilder;
import com.earnings.okhttputils.utils.OkHttp.callback.Callback;
import com.earnings.okhttputils.utils.OkHttp.request.RequestCall;
import com.earnings.okhttputils.utils.OkHttp.utils.Platform;
import com.earnings.okhttputils.utils.OkHttp.utils.SystemoutUtils;
import com.earnings.okhttputils.utils.car.http.GodLog;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.IOException;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Executor;

import okhttp3.Call;
import okhttp3.OkHttpClient;
import okhttp3.Response;


/**
 * Created by zhy on 15/8/17.
 */
public class OkHttpUtils {

    public static final String CACHE = "L_OkHttp";
    public static final long DEFAULT_MILLISECONDS = 10_000L;
    private volatile static OkHttpUtils mInstance;
    private OkHttpClient mOkHttpClient;
    private Platform mPlatform;

    public OkHttpUtils(OkHttpClient okHttpClient) {
        if (okHttpClient == null) {
            mOkHttpClient = new OkHttpClient();
        } else {
            mOkHttpClient = okHttpClient;
        }

        mPlatform = Platform.get();
    }

    public static OkHttpUtils initClient(OkHttpClient okHttpClient) {
        if (mInstance == null) {
            synchronized (OkHttpUtils.class) {
                if (mInstance == null) {
                    mInstance = new OkHttpUtils(okHttpClient);
                }
            }
        }
        return mInstance;
    }

    public static OkHttpUtils getInstance() {
        return initClient(null);
    }

    public static GetBuilder get() {
        return new GetBuilder();
    }

    public static PostStringBuilder postString() {
        return new PostStringBuilder();
    }

    public static PostFileBuilder postFile() {
        return new PostFileBuilder();
    }

    public static PostFormBuilder post() {
        return new PostFormBuilder();
    }

    public static OtherRequestBuilder put() {
        return new OtherRequestBuilder(METHOD.PUT);
    }

    public static HeadBuilder head() {
        return new HeadBuilder();
    }

    public static OtherRequestBuilder delete() {
        return new OtherRequestBuilder(METHOD.DELETE);
    }

    public static OtherRequestBuilder patch() {
        return new OtherRequestBuilder(METHOD.PATCH);
    }

    public Executor getDelivery() {
        return mPlatform.defaultCallbackExecutor();
    }

    public OkHttpClient getOkHttpClient() {
        return mOkHttpClient;
    }

    public void execute(final RequestCall requestCall, Callback callback) {
        if (callback == null)
            callback = Callback.CALLBACK_DEFAULT;
        final Callback finalCallback = callback;
        final int id = requestCall.getOkHttpRequest().getId();

        if (GodLog.DE_BUG) {
         //   GodLog.Log("请求URL = " + requestCall.getUrl());
            if (requestCall.getParams() != null) {
                String requestUrl = requestCall.getUrl();
                Map<String, String> params = requestCall.getParams();
                Set<String> keys = params.keySet();
                Iterator<String> iterator = keys.iterator();
                GodLog.Log("请求参数 : ↓");
                while (iterator.hasNext()) {
                    String key = iterator.next();
                    GodLog.Log(key + " : " + params.get(key));
                    if (iterator.hasNext()) requestUrl += key + "=" + params.get(key) + "&";
                    else requestUrl += key + "=" + params.get(key);
                }
                GodLog.Log("拼接参数后的请求URL =" + requestUrl);
            }
        }

        Context context = requestCall.getContext();
        if (context != null) {
//            boolean isCache=!checkNetworkState(context);
//            if(requestCall.getCacheMode() == RequestCall.CacheMode.ONLY_CACHE){
//                isCache=true;
//            }
            //网络不可用 或者是缓存模式
            if (requestCall.getCacheMode() == RequestCall.CacheMode.ONLY_CACHE) {
                SharedPreferences sharedPreferences = context.getSharedPreferences(OkHttpUtils.CACHE,
                        Context.MODE_PRIVATE);
                String str = sharedPreferences.getString(regexuURL(requestCall.getUrl()), "");
                String str_id = sharedPreferences.getString(regexuURL(requestCall.getUrl()) + "_id", "");
                if (!"".equals(str) && !"".equals(str_id)) {
                    if (SystemoutUtils.DE_BUG) {
                        String paramsStr = "";
                        if (requestCall.getParams() != null) {
                            Map<String, String> params = requestCall.getParams();
                            Set<String> keys = params.keySet();
                            Iterator<String> iterator = keys.iterator();
                            while (iterator.hasNext()) {
                                String key = iterator.next();
                                paramsStr = paramsStr + "" + key + ":" + params.get(key) + "\n";
                            }
                        }
                        try {
                            SystemoutUtils.Log("缓存\n" + requestCall.getUrl(), str, id + "", "参数:\n" + paramsStr);
                        } catch (Exception e) {
                            SystemoutUtils.Log("缓存\n" + requestCall.getUrl(), id + "", "参数:\n" + paramsStr);
                        }

                    }
                    sendSuccessResultCallback(str, finalCallback, id);
                    return;
                }
            }
        }

        requestCall.getCall().enqueue(new okhttp3.Callback() {
            @Override
            public void onFailure(Call call, final IOException e) {
                sendFailResultCallback(call, e, finalCallback, id);
            }

            @Override
            public void onResponse(final Call call, final Response response) {
                try {
                    if (call.isCanceled()) {
                        if (SystemoutUtils.DE_BUG) {
                            String paramsStr = "";
                            if (requestCall.getParams() != null) {
                                Map<String, String> params = requestCall.getParams();
                                Set<String> keys = params.keySet();
                                Iterator<String> iterator = keys.iterator();
                                while (iterator.hasNext()) {
                                    String key = iterator.next();
                                    paramsStr = paramsStr + "" + key + ":" + params.get(key) + "\n";
                                }
                            }
                            SystemoutUtils.Log("isCanceled------\n" + requestCall.getUrl(), id + "", "参数:\n" + paramsStr);
                        }
                        sendFailResultCallback(call, new IOException("Canceled!"), finalCallback, id);
                        return;
                    }

                    if (!finalCallback.validateReponse(response, id)) {
                        if (SystemoutUtils.DE_BUG) {
                            String paramsStr = "";
                            if (requestCall.getParams() != null) {
                                Map<String, String> params = requestCall.getParams();
                                Set<String> keys = params.keySet();
                                Iterator<String> iterator = keys.iterator();
                                while (iterator.hasNext()) {
                                    String key = iterator.next();
                                    paramsStr = paramsStr + "" + key + ":" + params.get(key) + "\n";
                                }
                            }
                            SystemoutUtils.Log(new IOException("request failed , reponse's code is : " + response.code()) + "\n" + requestCall.getUrl(), id + "", "参数:\n" + paramsStr);
                        }
                        sendFailResultCallback(call, new IOException("request failed , reponse's code is : " + response.code()), finalCallback, id);
                        return;
                    }

                    Object o = finalCallback.parseNetworkResponse(response, id);
                    if (requestCall.getContext() != null) {

                        if (o instanceof String) {
                            SharedPreferences sharedPreferences = requestCall.getContext().getSharedPreferences(OkHttpUtils.CACHE,
                                    Context.MODE_PRIVATE);
                            SharedPreferences.Editor editor = sharedPreferences.edit();

                            editor.putString(regexuURL(requestCall.getUrl()), (String) o);
                            editor.putString(regexuURL(requestCall.getUrl()) + "_id", id + "");
                            editor.apply();
                            if (SystemoutUtils.DE_BUG) {
                                String paramsStr = "";
                                if (requestCall.getParams() != null) {
                                    Map<String, String> params = requestCall.getParams();
                                    Set<String> keys = params.keySet();
                                    Iterator<String> iterator = keys.iterator();
                                    while (iterator.hasNext()) {
                                        String key = iterator.next();
                                        paramsStr = paramsStr + "" + key + ":" + params.get(key) + "\n";
                                    }
                                }
                                try {
                                    SystemoutUtils.Log("网络\n" + requestCall.getUrl(), ((String) o), id + "", "参数:\n" + paramsStr);
                                } catch (Exception e) {
//                                    SystemoutUtils.Log("参数过多所以异常在打印一次---网络\n" + requestCall.getUrl(), id + "", "参数:\n" + paramsStr);
                                }


                            }
                        }
                    }
                    sendSuccessResultCallback(o, finalCallback, id);
                } catch (Exception e) {
                    sendFailResultCallback(call, e, finalCallback, id);
                } finally {
                    if (response.body() != null)
                        response.body().close();
                }

            }
        });
    }


    public void sendFailResultCallback(final Call call, final Exception e, final Callback callback, final int id) {
        if (callback == null) return;

        mPlatform.execute(new Runnable() {
            @Override
            public void run() {
                callback.onError(call, e, id);
                callback.onAfter(id);
            }
        });
    }

    public void sendSuccessResultCallback(final Object object, final Callback callback, final int id) {
        if (callback == null) return;
        mPlatform.execute(new Runnable() {
            @Override
            public void run() {
                callback.onResponse(object, id);
                if (object instanceof String) {
                    JSONObject object1;
                    try {
                        object1 = new JSONObject((String) object);

                        callback.onResponse(object1, id, object1.optInt("status"), object1.optString("msg"));
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }


                }
                callback.onAfter(id);
            }
        });
    }

    public void cancelTag(Object tag) {
        for (Call call : mOkHttpClient.dispatcher().queuedCalls()) {
            if (tag.equals(call.request().tag())) {
                call.cancel();
            }
        }
        for (Call call : mOkHttpClient.dispatcher().runningCalls()) {
            if (tag.equals(call.request().tag())) {
                call.cancel();
            }
        }
    }

    private boolean checkNetworkState(Context context) {

        boolean flag = false;
        //得到网络连接信息
        ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        //去进行判断网络是否连接
        if (manager.getActiveNetworkInfo() != null) {
            flag = manager.getActiveNetworkInfo().isAvailable();
        }
        return flag;
    }

    public static class METHOD {
        public static final String HEAD = "HEAD";
        public static final String DELETE = "DELETE";
        public static final String PUT = "PUT";
        public static final String PATCH = "PATCH";
    }

    private String regexuURL(String URL) {
        String regexu1 = "sing=[0-9a-z]{1,}&";
        String regexu2 = "time=[0-9a-z]{1,}&";
        String str = URL.replaceAll(regexu1, "").replaceAll(regexu2, "");
        return str;
    }


}


